/**
 * @author: Miss.杨
 * @date: 2025年3月08日 16:01:23
 * @description: 
 */
package com.sheepone.monitor.audit.server;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;

import com.sheepone.monitor.audit.server.anno.StatusHandler;
import com.sheepone.monitor.audit.core.entities.AuditLogContext;
import com.sheepone.monitor.audit.core.entities.AuditLogMessage;
import com.sheepone.monitor.audit.core.felids.AuditLogFelids;
import com.sheepone.webdev.log.WebDevLogger;

/**
 * @author: Miss.杨
 * @date: 2025年3月08日 16:01:23
 * @description:
 */
public abstract class ActionHandler<E extends AuditLogFelids> {

    protected String infoMappingSplitter = ":";
    protected String infoCollectionValueSplitter = ",";
    protected String infoCollectionValuePrefix = "[";
    protected String infoCollectionValueSuffix = "]";
    protected String infoEntrySplitter = ";";

    private HashMap<String, Method> statusHandlers = new HashMap<>();

    private static WebDevLogger logger = WebDevLogger.getLogger(ActionHandler.class);

    public void init() {
        Method[] methods = this.getClass().getDeclaredMethods();
        for (Method method : methods) {
            if (method.isAnnotationPresent(StatusHandler.class)) {
                StatusHandler annotation = method.getAnnotation(StatusHandler.class);
                // TODO方法参数校验
                statusHandlers.put(annotation.value(), method);
            }
        }
    }

    public void prehandle(AuditLogContext context) {
        // TODO 对必要参数做校验或者采取默认值的方式
    }

    /**
     * 从上下文对象中提取出需要持久化的实体对象
     * 
     * @param context
     * @return
     */
    protected abstract E extractContext(AuditLogContext context);

    /**
     * 持久化实体对象
     * 
     * @param entity
     * @return
     */
    protected abstract void save(E entity);

    /**
     * 提供规范化OtherInfo的简单实现
     * 
     * @param context
     * @return
     */
    protected String parseInfo(AuditLogContext context) {
        HashMap<String, Object> otherInfo = context.getOtherInfo();
        if (otherInfo != null && !otherInfo.isEmpty()) {
            int infoIndex = 0;
            StringBuilder infoBuilder = new StringBuilder();
            for (Entry<String, Object> entry : otherInfo.entrySet()) {
                if (infoIndex > 0) {
                    infoBuilder.append(infoEntrySplitter);
                }
                Object value = entry.getValue();
                StringBuilder valueBuilder = new StringBuilder();
                if (value instanceof Collection) {
                    valueBuilder.append(infoCollectionValuePrefix);
                    int index = 0;
                    for (Object v : (Collection<?>) value) {
                        if (index > 0) {
                            valueBuilder.append(infoCollectionValueSplitter);
                        }
                        valueBuilder.append(v);
                        index++;
                    }
                    valueBuilder.append(infoCollectionValueSuffix);
                }
                infoBuilder.append(entry.getKey()).append(infoMappingSplitter).append(valueBuilder);
            }
            return infoBuilder.toString();
        }
        return "";
    }

    public void handle(AuditLogContext context) {
        AuditLogMessage message = context.getMessage();
        String status = message.getStatus();
        // 调用对应的状态处理器
        Method method = statusHandlers.get(status);
        if (method != null) {
            try {
                method.invoke(this, context);
            } catch (Exception e) {
                logger.error("{} handle for status:{} error:{}", this.getClass().getName(), status, e.getMessage());
            }
        }
        // 从上下文中提取实体信息
        E entity = extractContext(context);
        // 持久化实体
        save(entity);
    }
}
